﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace OmixJsonServer.Helpers
{
    public class JsonFormat
    {
        public string property { get; set; }
        public string directive { get; set; }
        public string display { get; set; }
        public string binding { get; set; }
        public object value { get; set; }
    }

    public static class JsonFormatterHelper
    {
        public static IEnumerable<JsonFormat> Transform(object obj, int level)
        {
            return GetJsonFormatItems(obj,level);
        }

        private static List<JsonFormat> GetJsonFormatItems(object obj, int level)
        {
            try
            {
                PropertyInfo[] properties = ReflectionHelper.GetProperties(obj);

                List<JsonFormat> lst = new List<JsonFormat>();

                foreach (var property in properties)
                {
                    if (level > 0)
                    {
                        JsonFormat jsonFormat = new JsonFormat
                        {
                            property = property.Name,
                            directive = GetDirective(property),
                            display = property.Name,
                            binding = GetBinding(property),
                            value = GetValue(property, obj, level - 1)
                        };

                        lst.Add(jsonFormat);
                    }
                }

                return lst;
            }
            catch (Exception exp)
            {
                throw exp;
            }
        }

        private static object GetValue(PropertyInfo p, object obj, int level)
        {
            object ret = null;

                if (ReflectionHelper.IsPropertyACollection(p))
                {
                    var arrayObject = ReflectionHelper.GetPropertyValue(obj, p.Name) as IEnumerable<object>;

                    List<List<JsonFormat>> extlst = new List<List<JsonFormat>>();

                    foreach (var item in arrayObject)
                    {
                        extlst.Add(GetJsonFormatItems(item, level));
                    }

                    ret = extlst;
                }
                else if (ReflectionHelper.IsPropertyAClass(p))
                {
                    var complexObject = ReflectionHelper.GetPropertyValue(obj, p.Name);

                    return GetJsonFormatItems(complexObject, level);
                }
                else
                {
                    ret = ReflectionHelper.GetPropertyValue(obj, p.Name);
                }

            return ret;
        }

        private static string GetBinding(PropertyInfo p)
        {
            return string.Empty;
        }


        private static string GetDirective(PropertyInfo p)
        {
            string ret = "text";

            if (ReflectionHelper.IsPropertyACollection(p))
            {
                ret = "array";
            }
            else if (ReflectionHelper.IsPropertyAClass(p))
            {
                ret = "object";
            }
            else
            {
                return "text";
            }

            return ret;
        }

        public static T Bind<T>(T setting, IEnumerable<JsonFormat> Items) where T : class
        {

            Func<string, IEnumerable<JsonFormat>> ConvertToItems = (Json) =>
            {
                return SerializationHelper.LoadFromJson<IEnumerable<JsonFormat>>(Json);
            };

            Items.ToList().ForEach(ji =>
            {
                try
                {
                    PropertyInfo PropInfo = ReflectionHelper.GetProperty(setting, ji.property);
                    var ValueToBind = ji.value;

                    var PropValue = new
                    {
                        Original = ji.value,
                        AsJson = SerializationHelper.SaveToJson(ji.value)
                    };

                    if (ReflectionHelper.IsPropertyAClass(PropInfo))
                    {

                        var Value = Activator.CreateInstance(PropInfo.PropertyType);
                        if (Value is IList)
                        {
                            IList ListValue = Value as IList;
                            Array ArrayItems = (Array)PropValue.Original;

                            foreach (var currentPropInfo in ArrayItems)
                            {
                                var BindItem = new
                                {
                                    ListItem = Activator.CreateInstance(ListValue.GetType().GetGenericArguments()[0]),
                                    JsonValue = SerializationHelper.SaveToJson(currentPropInfo)
                                };

                                ListValue.Add(Bind(BindItem.ListItem, ConvertToItems(BindItem.JsonValue)));
                            }

                            ValueToBind = ListValue;
                        }

                        else
                        {
                            IEnumerable<JsonFormat> items = ConvertToItems(SerializationHelper.SaveToJson(PropValue.Original));
                            ValueToBind = Bind(Value, items);
                        }

                    }

                    setting = ReflectionHelper.SetPropertyValue(setting, ji.property, ValueToBind);
                }
                catch (Exception ex)
                {

                    throw ex;
                }

            });

            return setting;
        }
    }
}
